home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 010 / blit.arc / BITBLT.C < prev    next >
Text File  |  1985-05-23  |  7KB  |  238 lines

  1. /*
  2.  * name:         bitblt
  3.  *
  4.  * description: copy the source rectangle r in a bitmap sb to the
  5.  *              corresponding rectangle with origin p in the destination
  6.  *              bitmap db using the optional halftone bitmap hb.
  7.  *              (algorithm snarfed from the 1st smalltalk-80 book)
  8.  *
  9.  * synopsis:     bitblt (sb, r, db, p, hb, f)
  10.  *              struct bitmap   *sb;
  11.  *              struct rectangle    *r;
  12.  *              struct bitmap   *db;
  13.  *              struct point    *p;
  14.  *              struct bitmap   *hb;
  15.  *              int      f;
  16.  *
  17.  * globals:      rightmasks  (r)
  18.  *              allones      (r)
  19.  *
  20.  * calls:        merge  (merge.c)
  21.  *
  22.  * called by:    addobs      (addobs.c)
  23.  *              screenswap   (screenswap.c)
  24.  *              newlayer     (newlayer.c)
  25.  *              background   (background.c)
  26.  *              lbblt        (lbblt.c)
  27.  *              rectf        (rectf.c)
  28.  */
  29. #include "layers.h"
  30.  
  31. unsigned short  rightmasks[] = {
  32.    0x0000,
  33.    0x0003, 0x000f,
  34.    0x003f, 0x00ff,
  35.    0x03ff, 0x0fff,
  36.    0x3fff, 0xffff
  37. };
  38. unsigned short allones = 0xffff;
  39.  
  40. bitblt (sb, r, db, p, hb, f)
  41. struct bitmap *sb;                     /* source bitmap */
  42. struct rectangle  *r;                  /* source rectangle */
  43. struct bitmap *db;                     /* destination bitmap */
  44. struct point  *p;                      /* point in destination bitmap to start
  45.                                          operation */
  46. struct bitmap *hb;                     /* halftone bitmap */
  47. int    f;                              /* operation to perform */
  48. {
  49.    int      sourceindex;
  50.    int      destindex;
  51.    int      sourcedelta;
  52.    int      destdelta;
  53.    boolean preload;
  54.    int      sx;
  55.    int      sy;
  56.    int      dx;
  57.    int      dy;
  58.    int      w;
  59.    int      h;
  60.    int      startpix;
  61.    int      endpix;
  62.    int      word;
  63.    int      skew;
  64.    int      nwords;
  65.    int      vdir;
  66.    int      hdir;
  67.    int      i;
  68.    unsigned short   merge ();
  69.    unsigned short   t;                 /* temp for exchanging masks */
  70.    unsigned short   prevword;
  71.    unsigned short   thisword;
  72.    unsigned short   skewword;
  73.    unsigned short   mergemask;
  74.    unsigned short   mergeword;
  75.    unsigned short   destword;
  76.    unsigned short   mask1;
  77.    unsigned short   mask2;
  78.    unsigned short   skewmask;
  79.    unsigned short   halftoneword;
  80.  
  81.  /*
  82.   * set w and h
  83.  */
  84.    w = r -> corner.x - r -> origin.x;
  85.    h = r -> corner.y - r -> origin.y;
  86.    if ((w <= 0) || (h <= 0))
  87.        return;                         /* null range */
  88.  /*
  89.   * calculate sx, sy, dx and dy
  90.  */
  91.    sx = r -> origin.x;
  92.    sy = r -> origin.y;
  93.    dx = p -> x;
  94.    dy = p -> y;
  95.  /*
  96.  * calculate skew and edge masks
  97.  */
  98.    skew = (sx - dx) % pixels_word;
  99.    if (skew < 0)
  100.        skew += pixels_word;
  101.  /*
  102.  * how many bits source gets skewed to right
  103.  */
  104.    startpix = pixels_word - (dx % pixels_word);
  105.  /*
  106.   * how many bits in first word
  107.  */
  108.    mask1 = rightmasks[startpix];
  109.    endpix = pixels_word - ((dx + w - 1) % pixels_word + 1);
  110.  /*
  111.   * how many bits in last word
  112.  */
  113.    mask2 = ~rightmasks[endpix];
  114.    skewmask = (skew == 0 ? 0 : rightmasks[pixels_word - skew]);
  115.  /*
  116.  * determine number of words stored per line
  117.  * merge masks if necessary
  118.  */
  119.    if (w <= startpix) {               /* i think this should be <=, not < */
  120.         mask1 = mask1 & mask2;
  121.        mask2 = 0;
  122.        nwords = 1;
  123.    }
  124.    else
  125.        nwords = ((w - startpix - 1) / pixels_word) + 2;
  126.  /*
  127.  * check for possible overlap of source and destination
  128.  */
  129.    hdir = vdir = 1;                    /* default for no overlap */
  130.    if ((sb == db) && (dy >= sy)) {
  131.        if (dy > sy) {                  /* have to start at bottom */
  132.            vdir = -1;
  133.            sy = sy + h - 1;
  134.            dy = dy + h - 1;
  135.        }
  136.         else {
  137.            if (dx > sx) {
  138.             /*
  139.             * y's are equal, but x's are backwards
  140.              */
  141.                hdir = -1;
  142.                sx = sx + w - 1;
  143.             /*
  144.             * start at right
  145.              */
  146.                dx = dx + w - 1;
  147.             /*
  148.              * and fix up masks
  149.              */
  150.                skewmask = ~skewmask;
  151.                t = mask1;
  152.                 mask1 = mask2;
  153.                mask2 = t;
  154.            }
  155.        }
  156.    }
  157.  /*
  158.  * check if need to reload buffer (i.e., two words of
  159.  * source needed for first word of destination)
  160.  */
  161.     preload = ((sb != null) && ((skew != 0) &&
  162.                ((dx % pixels_word) <= (sx % pixels_word))));
  163.    if (hdir < 0)
  164.        preload = !preload;
  165.  /*
  166.   * calculate starting offsets
  167.  */
  168.    if (sb != null)
  169.        sourceindex = (sy - sb -> bm_rect.origin.y) * sb -> bm_width +
  170.            (sx / pixels_word) -
  171.            (sb -> bm_rect.origin.x / pixels_word);
  172.    else
  173.        sourceindex = 0;
  174.    destindex = (dy - db -> bm_rect.origin.y) * db -> bm_width +
  175.        (dx / pixels_word) -
  176.        (db -> bm_rect.origin.x / pixels_word);
  177.  /*
  178.   * calculate increments from end of one line to start of next
  179.  */
  180.    if (sb != null)
  181.     sourcedelta = (sb -> bm_width * vdir) - ((nwords + (preload ? 1 : 0)) * hdir);
  182.    else
  183.        sourcedelta = 0;
  184.    destdelta = (db -> bm_width * vdir) - (nwords * hdir);
  185.  /*
  186.  * perform the data transfer
  187.  */
  188.    for (i = 1; i <= h; i++) {          /* this is the vertical loop */
  189.        if (hb != null) {
  190.            halftoneword = *(hb -> bm_base + (dy % pixels_word));
  191.            dy = dy + vdir;
  192.        }
  193.        else
  194.            halftoneword = allones;
  195.        skewword = halftoneword;
  196.        if (preload) {
  197.            prevword = *(sb -> bm_base + sourceindex);
  198.        /*
  199.         * load the 16-bit shifter
  200.         */
  201.            sourceindex = sourceindex + hdir;
  202.        }
  203.        else
  204.            prevword = 0;
  205.        mergemask = mask1;
  206.    /*
  207.     * here is the inner horizontal loop
  208.     */
  209.        for (word = 1; word <= nwords; word++) {
  210.            if (sb != null) {
  211.                 prevword = prevword & skewmask;
  212.             /*
  213.             * pick up next word
  214.              */
  215.                thisword = *(sb -> bm_base + sourceindex);
  216.                skewword = prevword | (thisword & ~skewmask);
  217.                prevword = thisword;
  218.             /*
  219.             * 16-bit rotate (actually, this code will work on 32-bit ints as well)
  220.              */
  221.                skewword = (skewword << skew) | (skewword >> (pixels_word - skew));
  222.            }
  223.            destword = *(db -> bm_base + destindex);
  224.            mergeword = merge ((skewword & halftoneword), destword, f);
  225.            *(db -> bm_base + destindex) = ((mergemask & mergeword) |
  226.                    (~mergemask & destword));
  227.            sourceindex = sourceindex + hdir;
  228.            destindex = destindex + hdir;
  229.            if (word == (nwords - 1))
  230.                mergemask = mask2;
  231.            else
  232.                mergemask = allones;
  233.        }
  234.        sourceindex = sourceindex + sourcedelta;
  235.        destindex = destindex + destdelta;
  236.    }
  237. }
  238.